/////////////////////////////////////////////////////////////////////////////
// 2023 -
//open source under Apache License Version 2.0
/////////////////////////////////////////////////////////////////////////////
//  Modifications by Kumo Inc.
// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <string>

#include <kmhdfs/client/erasure_coder.h>
#include <turbo/log/logging.h>
#include <turbo/strings/str_format.h>

namespace Hdfs {
    namespace Internal {
        std::string dumpCodingMatrix(unsigned char *buf, int n1, int n2) {
            std::string res = "[";
            int i, j;
            for (i = 0; i < n1; i++) {
                res += "[";
                for (j = 0; j < n2; j++) {
                    if (j > 0) res += " ";
                    res += std::to_string(0xff & buf[j + (i * n2)]);
                }
                res += "]";
            }
            res += "]";
            return res;
        }

        void dumpEncoder(IsalEncoder *pCoder) {
            int numDataUnits = pCoder->coder.numDataUnits;
            int numParityUnits = pCoder->coder.numParityUnits;
            int numAllUnits = pCoder->coder.numAllUnits;

            std::string encodeMatrixStr = dumpCodingMatrix((unsigned char *) pCoder->encodeMatrix,
                                                           numDataUnits, numAllUnits).c_str();

            KLOG(INFO) << turbo::str_format(
                          "Encoding (numAllUnits = %d, numParityUnits = %d, numDataUnits = %d), EncodeMatrix = %s",
                          numAllUnits, numParityUnits, numDataUnits, encodeMatrixStr.c_str());
        }

        void dumpDecoder(IsalDecoder *pCoder) {
            int i, j;
            int numDataUnits = pCoder->coder.numDataUnits;
            int numAllUnits = pCoder->coder.numAllUnits;

            std::string erasedIndexesStr = "[";
            for (j = 0; j < pCoder->numErased; j++) {
                if (j > 0) erasedIndexesStr += " ";
                erasedIndexesStr += std::to_string(pCoder->erasedIndexes[j]);
            }
            erasedIndexesStr += "]";

            std::string decodeIndexesStr = "[";
            for (i = 0; i < numDataUnits; i++) {
                if (i > 0) decodeIndexesStr += " ";
                decodeIndexesStr += std::to_string(pCoder->decodeIndex[i]);
            }
            decodeIndexesStr += "]";

            std::string EncodeMatrixStr = dumpCodingMatrix((unsigned char *) pCoder->encodeMatrix,
                                                           numDataUnits, numAllUnits);

            std::string InvertMatrixStr = dumpCodingMatrix((unsigned char *) pCoder->invertMatrix,
                                                           numDataUnits, numAllUnits);

            std::string DecodeMatrixStr = dumpCodingMatrix((unsigned char *) pCoder->decodeMatrix,
                                                           numDataUnits, numAllUnits);

            KLOG(INFO) << turbo::str_format(
                          "Recovering (numAllUnits = %d, numDataUnits = %d, numErased = %d), ErasedIndexes = %s, "
                          "DecodeIndexes = %s, EncodeMatrix = %s, InvertMatrix = %s, DecodeMatrix = %s",
                          numAllUnits, numDataUnits, pCoder->numErased, erasedIndexesStr.c_str(),
                          decodeIndexesStr.c_str(),
                          EncodeMatrixStr.c_str(), InvertMatrixStr.c_str(), DecodeMatrixStr.c_str());
        }
    }
}
